#region Summary

// 
// Owner : JackieHan 
// 
// Solution : Jackie.Utility 
// 
// Project : Jackie.Utility
// 
// File : JQGird.cs
// 
// CopyRight : Copyright © 2010-2011 Skomart Corporation, All Rights Reserved 
// 
// Summary : JQuery JQGrid Class
// 
// History : 
//			2010-10-15 13:15:20	    Create 
// 

#endregion

#region Using

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using System.Reflection;
using System.Web;
using System.Web.Mvc;

#endregion

namespace Jackie.Utility.JQuery.Grid
{
    /// <summary> 
    /// JQuery JQGrid Class
    /// </summary>
    public class JQGrid
    {
        public JQGrid()
        {
            DataType = DataType.Json;
            RowNum = 20;
            RowList = new List<int> { 20, 30, 40 };
            CommonButton = new JQGridCommonButton();
            ViewRecords = true;
            Multiselect = false;
            ToolBar = new JQGridToolBar();
            AutoWidth = false;
        }

        /// <summary>
        /// Grid 标识  用于生成table和pageDiv的Id
        /// </summary>
        public string Id { get; set; }
        /// <summary>
        /// 获取数据的Url
        /// </summary>
        public string DataUrl { get; set; }
        /// <summary>
        /// 数据类型
        /// </summary>
        public DataType DataType { get; set; }
        /// <summary>
        /// 列集合
        /// </summary>
        public IList<JQGridColumn> Columns { get; set; }
        /// <summary>
        /// 页行数
        /// </summary>
        public int RowNum { get; set; }
        /// <summary>
        /// 分页行数 选择
        /// </summary>
        public IList<int> RowList { get; set; }
        /// <summary>
        /// ?
        /// </summary>
        public bool ViewRecords { get; set; }
        /// <summary>
        /// 默认排序绑定字段
        /// </summary>
        public string DefaultSortField { get; set; }
        /// <summary>
        /// 默认排序方式
        /// </summary>
        public SortType DefaultSortType { get; set; }
        /// <summary>
        /// Grid标题
        /// </summary>
        public string Caption { get; set; }
        /// <summary>
        /// 高度
        /// </summary>
        public int Height { get; set; }
        /// <summary>
        /// autowidth 设置为true，grid的宽度会根据父元素的宽度自动重新计算。注意，这个值是在初始化的时候设定好了，如果要在运行中设置宽度，需要通过setGridWidth方法来修改。
        /// </summary>
        public bool AutoWidth { get; set; }
        /// <summary>
        /// 宽度
        /// </summary>
        public int Width { get; set; }
        /// <summary>
        /// 命令按钮
        /// </summary>
        public JQGridCommonButton CommonButton { get; set; }
        /// <summary>
        /// 支持多选
        /// </summary>
        public bool Multiselect { get; set; }
        /// <summary>
        /// 工具栏选项
        /// </summary>
        public JQGridToolBar ToolBar { get; set; }

        /// <summary>
        /// 是否显示快捷搜索栏
        /// </summary>
        public bool ShowSearchToolBar { get; set; }

        #region DataBind

        /// <summary>
        /// 创建JQGrid的绑定json对象
        /// </summary>
        /// <param name="dataSource"></param>
        /// <returns></returns>
        public JsonResult DataBind(IQueryable dataSource)
        {
            IQueryable tempDataSource = dataSource;
            int currentPage, pageSize;
            string orderField, orderType;
            bool isSearch;

            currentPage = JackieConvertor.ToInt(GetParameter("page"));
            pageSize = JackieConvertor.ToInt(GetParameter("rows"));
            orderField = GetParameter("sidx");
            orderType = GetParameter("sord");
            isSearch = JackieConvertor.ToBoolean(GetParameter("_search"));

            int totalRowCount = tempDataSource.Count();
            int totalPagesCount = (int)Math.Ceiling((double)((float)totalRowCount / (float)pageSize));

            if (string.IsNullOrEmpty(orderField))
            {
                orderField = GetPrimaryKey();
            }

            string ordering = orderField + " " + orderType;

            if (isSearch)
            {
                string whereCause = GetWhereCause();
                tempDataSource = tempDataSource.Where(whereCause, new object[0]);
                //重新计算
                totalRowCount = tempDataSource.Count();
                totalPagesCount = (int)Math.Ceiling((double)((float)totalRowCount / (float)pageSize));

                tempDataSource = tempDataSource.Skip((currentPage - 1) * pageSize).Take(pageSize);
            }
            else
            {
                tempDataSource = tempDataSource.OrderBy(ordering, new object[0]).Skip((currentPage - 1) * pageSize).Take(pageSize);
            }

            JsonDataForJQGrid dataForJqGrid = new JsonDataForJQGrid(currentPage, totalPagesCount, totalRowCount,
                                                                    tempDataSource.Count());

            JsonResult jsonResult = new JsonResult();
            jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            if (tempDataSource.Count() == 0)
                dataForJqGrid.page = 0;
            jsonResult.Data = PrepareJQGridData(dataForJqGrid, this, tempDataSource);
            return jsonResult;
        }

        /// <summary>
        /// 获取搜索时的条件集合
        /// </summary>
        /// <returns></returns>
        private string GetWhereCause()
        {
            string whereCause = string.Empty;
            foreach (JQGridColumn column in Columns)
            {
                string queryString = string.IsNullOrEmpty(column.IndexField) ? column.DataField : column.IndexField;
                string searchFieldValue = GetParameter(queryString);
                if (!string.IsNullOrEmpty(searchFieldValue))
                {
                    string columnSearchCondition = GetColumnSearchCondition(searchFieldValue, column);
                    if (string.IsNullOrEmpty(whereCause))
                        whereCause += columnSearchCondition;
                    else
                        whereCause += "&&" + columnSearchCondition;
                }
            }
            return whereCause;
        }

        /// <summary>
        /// 搜索条件连接
        /// </summary>
        /// <param name="searchFieldValue"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        private string GetColumnSearchCondition(string searchFieldValue, JQGridColumn column)
        {
            string indexField = string.IsNullOrEmpty(column.IndexField) ? column.DataField : column.IndexField;
            string conditionExpression;
            conditionExpression = GetConditionExpression(column, searchFieldValue);
            switch (column.SearchOptions.SearchOperation)
            {
                case SearchOperation.Equal:
                    return string.Format(conditionExpression, indexField, "=", searchFieldValue);
                case SearchOperation.NotEqual:
                    return string.Format(conditionExpression, indexField, "!=", searchFieldValue);
                case SearchOperation.Greater:
                    return string.Format(conditionExpression, indexField, ">", searchFieldValue);
                case SearchOperation.GreaterOrEqual:
                    return string.Format(conditionExpression, indexField, ">=", searchFieldValue);
                case SearchOperation.Less:
                    return string.Format(conditionExpression, indexField, "<", searchFieldValue);
                case SearchOperation.LessOrEqual:
                    return string.Format(conditionExpression, indexField, "<=", searchFieldValue);
                case SearchOperation.BeginWith:
                    return string.Format("{0}.StartsWith(\"{1}\")", indexField, searchFieldValue);
                case SearchOperation.NotBeginWith:
                    return string.Format("!{0}.StartsWith(\"{1}\")", indexField, searchFieldValue);
                case SearchOperation.EndWith:
                    return string.Format("{0}.EndsWith(\"{1}\")", indexField, searchFieldValue);
                case SearchOperation.NotEndWith:
                    return string.Format("!{0}.EndsWith(\"{1}\")", indexField, searchFieldValue);
                case SearchOperation.Contain:
                    return string.Format("{0}.Contains(\"{1}\")", indexField, searchFieldValue);
                case SearchOperation.NotContain:
                    return string.Format("!{0}.Contains(\"{1}\")", indexField, searchFieldValue);
            }
            throw new Exception("Invalid search operation!");
        }

        /// <summary>
        /// 根据列的数据类型获取条件表达式
        /// </summary>
        /// <remarks>
        /// 主要是DateTime类型和Float类型需要转换
        /// </remarks>
        /// <param name="column"></param>
        /// <param name="searchFieldValue"></param>
        /// <returns></returns>
        private string GetConditionExpression(JQGridColumn column, string searchFieldValue)
        {
            string conditionExpression;
            if (column.DataType == JQGridColumnDataType.String)
                conditionExpression = "{0}{1}\"{2}\"";
            else if (column.DataType == JQGridColumnDataType.DateTime)
            {
                DateTime dateTime = JackieConvertor.ToDateTime(searchFieldValue);
                string datetimeStr = string.Format("DateTime({0},{1},{2})", dateTime.Year, dateTime.Month, dateTime.Day);
                conditionExpression = "{0}{1}" + datetimeStr;
            }
            else if ((column.DataType == JQGridColumnDataType.FloatNumber) && (searchFieldValue.Contains(".")))
                conditionExpression = "{0}{1}{2}F";
            else
                conditionExpression = "{0}{1}{2}";
            return conditionExpression;
        }


        /// <summary>
        /// 获取网页提交参数值  分Post和Get类型
        /// </summary>
        /// <param name="parameterStr">参数</param>
        /// <returns></returns>
        private string GetParameter(string parameterStr)
        {
            string parameterValue;
            var currentRequest = HttpContext.Current.Request;
            if (currentRequest.RequestType == "POST")
            {
                parameterValue = currentRequest.Form[parameterStr];
            }
            else
            {
                parameterValue = currentRequest.QueryString[parameterStr];
            }
            return parameterValue;
        }

        /// <summary>
        /// 获取标志位PrimaryKey的列的绑定，如果没有默认返回第一列
        /// </summary>
        /// <returns></returns>
        private string GetPrimaryKey()
        {
            string primaryKey = string.Empty;
            foreach (JQGridColumn column in Columns)
            {
                if (column.PrimaryKey)
                {
                    primaryKey = column.DataField;
                }
            }
            if (string.IsNullOrEmpty(primaryKey))
                primaryKey = Columns[0].DataField;
            return primaryKey;
        }

        /// <summary>
        /// 准备JQGrid的json绑定数据对象
        /// </summary>
        /// <param name="dataForJqGrid"></param>
        /// <param name="jQGird"></param>
        /// <param name="dataSource"></param>
        /// <returns></returns>
        private JsonDataForJQGrid PrepareJQGridData(JsonDataForJQGrid dataForJqGrid, JQGrid jQGird, IQueryable dataSource)
        {
            int i = 0;
            foreach (var dataObject in dataSource)
            {
                string[] rowValueAttr = new string[jQGird.Columns.Count];
                int j = 0;
                int primaryKeyIndex = 0;
                foreach (JQGridColumn jqGridColumn in jQGird.Columns)
                {
                    if (jqGridColumn.PrimaryKey)
                        primaryKeyIndex = j;
                    string columnValueStr = "";
                    if (!string.IsNullOrEmpty(jqGridColumn.DataField))
                    {
                        Type dataObjectType = dataObject.GetType();
                        PropertyInfo columnProperty = dataObjectType.GetProperty(jqGridColumn.DataField);
                        object propertyValue = columnProperty.GetValue(dataObject, null);
                        columnValueStr = propertyValue == null ? string.Empty : propertyValue.ToString();
                    }
                    rowValueAttr[j++] = columnValueStr;
                }

                string keyValue = rowValueAttr[primaryKeyIndex];

                JsonRowForJQGrid jsonRow = new JsonRowForJQGrid();
                jsonRow.id = keyValue;
                jsonRow.cell = rowValueAttr;

                dataForJqGrid.rows[i++] = jsonRow;
            }
            return dataForJqGrid;
        }

        #endregion
    }
}